﻿using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System.Net.WebSockets;
using System.Text;

namespace Polaris.Common.Socket
{
    /// <summary>
    /// 自定义 WebSocket 中间件
    /// </summary>
    public class WebSocketManagerMiddleware
    {
        private readonly RequestDelegate _next;
        private WebSocketHandler _webSocketHandler { get; set; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="next"></param>
        /// <param name="webSocketHandler"></param>
        public WebSocketManagerMiddleware(RequestDelegate next,
                                          WebSocketHandler webSocketHandler)
        {
            _next = next;
            _webSocketHandler = webSocketHandler;
        }

        public async Task Invoke(HttpContext context)
        {
            if (!context.WebSockets.IsWebSocketRequest)
            {
                await _next.Invoke(context);
                return;
            }

            //接受 websocket 客户端连接  // 转换当前连接为一个 ws 连接
            var socket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false);

            var message = "";
            //Message message = new Message();
            //// 获取参数
            //message.userName = context.Request.Query["userName"].ToString();
            //message.methodName = context.Request.Query["methodName"].ToString();
            //string socketId = string.Format("{0}_{1}", message.userName, message.editId);
            //string socketId = string.Format("{0}_{1}", "", "");

            //string socketId = Guid.NewGuid().ToString();
            //await _webSocketHandler.OnConnected(socketId, socket).ConfigureAwait(false);

            //await MessageHandle(socket, socketId, JsonConvert.SerializeObject(message));

            await Receive(socket, async (result, serializedMessage) =>
            {
                if (result.MessageType == WebSocketMessageType.Text)
                {
                    try
                    {
                        //Message message = JsonConvert.DeserializeObject<Message>(serializedMessage);
                        string message = serializedMessage;
                        Console.WriteLine(message + "---" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        if (message.Contains("getSocketId:"))
                        {
                            string socketId = Guid.NewGuid().ToString();
                            //添加指定socket
                            await _webSocketHandler.OnConnected(socketId, socket).ConfigureAwait(false);
                            await _webSocketHandler.SendMessageAsync(socketId, "socketId:" + socketId).ConfigureAwait(false);
                        }
                        //var socketIds = await MessageHandle(socket, socketId, message);
                        //if (message.messageState == MessageState.BeApplied || message.messageState == MessageState.BeDisAgreed || message.messageState == MessageState.BeAgreed)
                        //{
                        //    await _webSocketHandler.SendMessageAsync(socketIds, message).ConfigureAwait(false);
                        //}
                        //else
                        //{
                        //    await _webSocketHandler.ReceiveAsync(socket, result, message).ConfigureAwait(false);
                        //}
                    }
                    catch (Exception)
                    {
                        socket.Abort();
                    }
                    return;
                }
                else if (result.MessageType == WebSocketMessageType.Close)
                {
                    try
                    {
                        await _webSocketHandler.OnDisconnected(socket);
                    }
                    catch (WebSocketException)
                    {
                        throw; //let's not swallow any exception for now
                    }
                    return;
                }
            });
        }

        private async Task Receive(WebSocket socket, Action<WebSocketReceiveResult, string> handleMessage)
        {
            // 判断连接类型，并执行相应操作
            while (socket.State == WebSocketState.Open)
            {
                ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[1024 * 4]);
                string message = null;
                WebSocketReceiveResult result = null;
                try
                {
                    using (var ms = new MemoryStream())
                    {
                        do
                        {
                            // 继续接受信息
                            result = await socket.ReceiveAsync(buffer, CancellationToken.None).ConfigureAwait(false);
                            ms.Write(buffer.Array, buffer.Offset, result.Count);
                        }
                        while (!result.EndOfMessage);

                        ms.Seek(0, SeekOrigin.Begin);

                        using (var reader = new StreamReader(ms, Encoding.UTF8))
                        {
                            message = await reader.ReadToEndAsync().ConfigureAwait(false);
                        }
                    }

                    handleMessage(result, message);
                }
                catch (WebSocketException e)
                {
                    if (e.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely)
                    {
                        socket.Abort();
                    }
                }
            }

            await _webSocketHandler.OnDisconnected(socket);
        }

        /// <summary>
        /// 消息处理
        /// </summary>
        /// <returns></returns>
        private async Task<List<string>> MessageHandle(WebSocket socket, string socketId, string message)
        {
            //获取所有连接
            var socketKeyValues = await _webSocketHandler.GetAll();
            var socketIds = socketKeyValues.Where(x => x.Key.Contains(message) && !x.Key.Equals(socketId)).Select(x => x.Key).ToList();

            if (socketIds != null && socketIds.Count > 0)
            {
                await _webSocketHandler.SendMessageAsync(socket, message);
            }
            else
            {

            }


            return socketIds;
        }
    }
}
